package com.ease.job.quartz.support;

import java.io.Serializable;
import java.text.ParseException;
import java.util.Date;
import java.util.UUID;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.quartz.CronExpression;
import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SimpleTrigger;
import org.quartz.Trigger;

import com.ease.common.util.Detect;

/**
 * http://www.javaeye.com/topic/399980 需要实现java.io.Serializable接口,否则会报 引用 Caused by: java.io.InvalidClassException:
 * com.sundoctor.example.service.SimpleService; class invalid for deserialization at
 * java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:587) at
 * java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1583) at
 * java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1496) at
 * java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1732) ... 64 more
 * 
 */
public class CronJobExecutor extends Detect implements Serializable {

	/**
	 *
	 */
	private static final long serialVersionUID = 6029687305124087255L;

	private static final transient Log log = LogFactory.getLog(CronJobExecutor.class);

	/** */
	private Scheduler scheduler;

	/** */
	private JobDetail jobDetail;

	public void init() {
		// try {
		// scheduler.addJob(jobDetail, true);
		// } catch (SchedulerException e) {
		// log.error("scheduler.addJob(jobDetail=" + jobDetail + ", true)", e);
		// }
	}

	public CronJobStatus getCronJobStatus() {
		try {
			return (scheduler.isStarted() ? (scheduler.isInStandbyMode() ? CronJobStatus.SHUTDOWN : CronJobStatus.RUNNING) : CronJobStatus.SHUTDOWN);
		} catch (Exception e) {
			return CronJobStatus.UNKNOWN;
		}
	}

	public void pause() {
		try {
			scheduler.standby();
		} catch (Exception e) {
			log.error("scheduler.standby()", e);
		}
	}

	public void shutdown() {
		try {
			scheduler.shutdown();
		} catch (Exception e) {
			log.error("scheduler.shutdown()", e);
		}
	}

	public void start() {
		try {
			scheduler.start();

		} catch (Exception e) {
			log.error("scheduler.start()", e);
		}
	}

	public void reschedule(String cronExpression) {
		reschedule(null, cronExpression);
	}

	public void reschedule(String triggerName, String cronExpression) {
		try {
			reschedule(triggerName, new CronExpression(cronExpression));
		} catch (ParseException e) {
			log.error("new CronExpression(cronExpression=" + cronExpression + ")", e);
		}
	}

	public void reschedule(CronExpression cronExpression) {
		reschedule(null, cronExpression);
	}

	public void reschedule(String triggerName, CronExpression cronExpression) {
		Trigger trigger = buildTigger(triggerName, cronExpression);
		reschedule(triggerName, trigger);
	}

	public void reschedule(Date startTime, Date endTime, int repeatCount, long repeatInterval) {
		reschedule(null, startTime, endTime, repeatCount, repeatInterval);
	}

	public void reschedule(String triggerName, Date startTime, Date endTime, int repeatCount, long repeatInterval) {
		Trigger trigger = buildTigger(triggerName, startTime, endTime, repeatCount, repeatInterval);
		reschedule(triggerName, trigger);
	}

	public void reschedule(String triggerName, Trigger trigger) {
		try {

			JobDetail existsJobDetail = scheduler.getJobDetail(jobDetail.getName(), jobDetail.getGroup());

			// 如果jobdetail已经存在,则删除旧的触发器
			if (null != existsJobDetail) {
				Trigger[] oldTriggers = scheduler.getTriggersOfJob(jobDetail.getName(), jobDetail.getGroup());
				if (null != oldTriggers && 0 < oldTriggers.length) {
					for (Trigger oldTrigger : oldTriggers) {
						scheduler.unscheduleJob(oldTrigger.getName(), oldTrigger.getGroup());
					}
				}
				scheduler.deleteJob(jobDetail.getName(), jobDetail.getGroup());
			}

			// Trigger trigger = scheduler.getTrigger(triggerName, Scheduler.DEFAULT_GROUP);
			// 关联任务和触发器
			scheduler.scheduleJob(jobDetail, trigger);
			// scheduler.scheduleJob(trigger);

			scheduler.rescheduleJob(triggerName, Scheduler.DEFAULT_GROUP, trigger);
		} catch (SchedulerException e) {
			log.error("scheduler.rescheduleJob(triggerName=" + triggerName + ", Scheduler.DEFAULT_GROUP, trigger=" + trigger + ")", e);
			throw new RuntimeException(e);
		}
	}

	public Trigger buildTigger(String triggerName, CronExpression cronExpression) {
		triggerName = buildTiggerName(triggerName);
		CronTrigger cronTrigger = new CronTrigger(triggerName, Scheduler.DEFAULT_GROUP, jobDetail.getName(), Scheduler.DEFAULT_GROUP);
		cronTrigger.setCronExpression(cronExpression);
		return cronTrigger;
	}

	public Trigger buildTigger(String triggerName, Date startTime, Date endTime, int repeatCount, long repeatInterval) {
		triggerName = buildTiggerName(triggerName);
		SimpleTrigger simpleTrigger = new SimpleTrigger(triggerName, Scheduler.DEFAULT_GROUP, jobDetail.getName(), Scheduler.DEFAULT_GROUP, startTime, endTime, repeatCount, repeatInterval);
		reschedule(triggerName, simpleTrigger);
		return simpleTrigger;
	}

	public String buildTiggerName(String triggerName) {
		if (!notEmpty(triggerName)) {
			triggerName = UUID.randomUUID().toString();
		}
		return triggerName;
	}

	/**
	 * @return the scheduler
	 */
	public Scheduler getScheduler() {
		return scheduler;
	}

	/**
	 * @param scheduler
	 *            the scheduler to set
	 */
	public void setScheduler(Scheduler scheduler) {
		this.scheduler = scheduler;
	}

	/**
	 * @return the jobDetail
	 */
	public JobDetail getJobDetail() {
		return jobDetail;
	}

	/**
	 * @param jobDetail
	 *            the jobDetail to set
	 */
	public void setJobDetail(JobDetail jobDetail) {
		this.jobDetail = jobDetail;
	}

}